<?php

if (!defined('MOODLE_INTERNAL')) {
    die('Direct access to this script is forbidden.');
}

global $CFG;
require_once($CFG->dirroot . '/blocks/formal_langs/tokens_base.php');

class block_formal_langs_tokens_base_test extends UnitTestCase {

    public function test_node_position_constructor() {
        $pos = new block_formal_langs_node_position(0,10,0,5);
        $this->assertNotNull($pos);
        $this->assertIsA($pos, 'block_formal_langs_node_position');

        $this->assertEqual($pos->linestart(), 0);
        $this->assertEqual($pos->lineend(),   10);
        $this->assertEqual($pos->colstart(),  0);
        $this->assertEqual($pos->colend(),    5);
    }

    public function test_node_position_summ_1() {
        /*
           012345678910
          +-----------
         0|00011122
         1|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 0, 3);
        $p[] = new block_formal_langs_node_position(0, 0, 3, 6);
        $p[] = new block_formal_langs_node_position(0, 0, 6, 8);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   0);
        $this->assertEqual($result->colstart(),  0);
        $this->assertEqual($result->colend(),    8);
    }

    public function test_node_position_summ_2() {
        /*
           012345678910
          +-----------
         0| 000 111 22
         1|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 4);
        $p[] = new block_formal_langs_node_position(0, 0, 5, 8);
        $p[] = new block_formal_langs_node_position(0, 0, 9, 11);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   0);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    11);
    }

    public function test_node_position_summ_3() {
        /*
           012345678910
          +-----------
         0| 000
         1|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 4);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   0);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    4);
    }

    
    public function test_node_position_summ_4() {
        /*
           012345678910
          +-----------
         0| 00N
         1|00
         2|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 1, 1, 3);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   1);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    3);
    }

    public function test_node_position_summ_5() {
        /*
           012345678910
          +-----------
         0| 00 11N
         1|11   22
         2|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 3);
        $p[] = new block_formal_langs_node_position(0, 1, 4, 2);
        $p[] = new block_formal_langs_node_position(1, 1, 5, 7);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   1);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    7);
    }

    public function test_node_position_summ_6() {
        /*
           012345678910
          +-----------
         0| 00 11N
         1|11   22N
         2|222
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 3);
        $p[] = new block_formal_langs_node_position(0, 1, 4, 2);
        $p[] = new block_formal_langs_node_position(1, 2, 5, 3);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   2);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    3);
    }

    public function test_node_position_summ_7() {
        /*
           012345678910
          +-----------
         0| 00XXX111
         1|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 6);
        $p[] = new block_formal_langs_node_position(0, 0, 3, 9);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   0);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    9);
    }

    public function test_node_position_summ_8() {
        /*
           012345678910
          +-----------
         0| 00XXX11N
         1|111XXX2
         2|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 6);
        $p[] = new block_formal_langs_node_position(0, 1, 3, 6);
        $p[] = new block_formal_langs_node_position(1, 1, 3, 7);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   1);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    7);
    }

    public function test_node_position_summ_9() {
        /*
           012345678910
          +-----------
         0| 00XXX11N
         1|N
         2|N
         3|11
         4|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 6);
        $p[] = new block_formal_langs_node_position(0, 3, 3, 2);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   3);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    2);
    }

    public function test_node_position_summ_10() {
        /*
           012345678910
          +-----------
         0| 000N
         1|N
         2|   22N
         3|11
         4|
         */
        
        $p = array();
        $p[] = new block_formal_langs_node_position(0, 0, 1, 4);
        $p[] = new block_formal_langs_node_position(2, 2, 3, 5);
        $p[] = new block_formal_langs_node_position(3, 3, 0, 2);

        $result = block_formal_langs_node_position::summ($p);
        $this->assertEqual($result->linestart(), 0);
        $this->assertEqual($result->lineend(),   3);
        $this->assertEqual($result->colstart(),  1);
        $this->assertEqual($result->colend(),    2);
    }

    public function test_node_base_contructor() {
        $pos = new block_formal_langs_node_position(0, 0, 1, 4);
        $node = new block_formal_langs_ast_node_base(0, $pos, 1, false);

        $this->assertNotNull($node);
        $this->assertIsA($node, 'block_formal_langs_ast_node_base');
        $this->assertEqual($node->type(), 0);
        $this->assertEqual($node->number(), 1);
        $node->set_number(2);
        $this->assertEqual($node->number(), 2);
        $this->assertEqual($node->position(), $pos);
        $newpos = new block_formal_langs_node_position(0, 0, 2, 8);
        $node->set_position($newpos);
        $this->assertEqual($node->position(), $newpos);
        $this->assertFalse($node->need_user_description());
        $this->assertEqual($node->description(), '');
        $node->set_description('desc');
        $this->assertEqual($node->description(), 'desc');
        $this->assertFalse($node->childs());
        $this->assertTrue($node->is_leaf());
        $pos_a = new block_formal_langs_node_position(0, 0, 4, 8);
        $pos_b = new block_formal_langs_node_position(0, 0, 8, 12);
        $node_a = new block_formal_langs_ast_node_base(1, $pos_a, 2, false);
        $node_b = new block_formal_langs_ast_node_base(2, $pos_b, 3, false);
        $node->add_child($node_a);
        $childs_a = array();
        $childs_a[] = $node_a;
        $this->assertEqual($node->childs(), $childs_a);
        $childs_b = array();
        $childs_b[] = $node_a;
        $childs_b[] = $node_b;
        $node->set_childs($childs_b);
        $this->assertEqual($node->childs(), $childs_b);
        $this->assertFalse($node->is_leaf());
    }


    public function test_token_base_constructor() {
        $pos = new block_formal_langs_node_position(0, 0, 1, 4);
        $token = new block_formal_langs_token_base(2, 1, 'abc', $pos, 1);

        $this->assertNotNull($token);
        $this->assertIsA($token, 'block_formal_langs_token_base');
        $this->assertEqual($token->value(), 'abc');
        $this->assertEqual($token->token_index(), 1);
        $token->set_token_index(4);
        $this->assertEqual($token->token_index(), 4);
    }

    public function test_token_base_editing_distance() {
        /* TODO: */
    }

    public function test_token_base_damerau_levenshtein() {
        /* TODO: */
    }

    public function test_token_base_is_same() {
        $pos_a = new block_formal_langs_node_position(0, 0, 4, 8);
        $pos_b = new block_formal_langs_node_position(0, 0, 8, 12);
        $pos_c = new block_formal_langs_node_position(0, 0, 8, 12);
        $token_a = new block_formal_langs_token_base(1, 2, 'atoken', $pos_a, 2);
        $token_b = new block_formal_langs_token_base(2, 3, 'btoken', $pos_b, 3);
        $token_c = new block_formal_langs_token_base(2, 3, 'btoken', $pos_c, 3);

        $this->assertFalse($token_a->is_same($token_b));
        $this->assertTrue($token_b->is_same($token_c));
    }

    public function test_ast_constructor() {
        /* TODO: */
    }

    public function test_ast_traverse() {
        /* TODO: */
    }

    public function test_ast_update_positions() {
        /* TODO: */
    }
}
 ?>